#include <pthread.h>
#include <mqueue.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <signal.h>

#define BUF_LEN 2048

static char recv_buf[BUF_LEN];
static char send_buf[BUF_LEN];

static mqd_t my_mq;
static mqd_t peer_mq;

static pthread_t recv_thread;

static char *my_mq_name = NULL;

void *recv_thread_func(void *argv)
{
    char *peer = argv;
    while (1)
    {
        int result = mq_receive(peer_mq, recv_buf, BUF_LEN, 0);
        if (result < 0)
        {
            continue;
        }
        printf("%s: %s\n", peer, recv_buf);
    }
}

void signal_handler(int sig)
{
    if (my_mq_name)
    {
        mq_unlink(my_mq_name);
        free(my_mq_name);
        exit(EXIT_SUCCESS);
    }
}

/**
 * @brief
 *
 * @param argc 参数数量应该为3个
 * @param argv argv[1]为自己的名字 argv[2]为对端的名字
 * @return int
 */
int main(int argc, char const *argv[])
{
    signal(SIGINT, signal_handler);
    signal(SIGTERM, signal_handler);
    if (argc < 3)
    {
        printf("参数不足\n");
        exit(EXIT_FAILURE);
    }

    sprintf(send_buf, "/%s", argv[1]);
    my_mq_name = malloc(strlen(send_buf) + 1);
    if (my_mq_name)
    {
        strcpy(my_mq_name, send_buf);
    }

    // 创建自己的消息队列
    struct mq_attr attr;
    attr.mq_maxmsg = 10;
    attr.mq_msgsize = BUF_LEN;

    my_mq = mq_open(send_buf, O_CREAT | O_RDWR, 0644, &attr);

    if (my_mq < 0)
    {
        perror("mq_open");
        exit(EXIT_FAILURE);
    }

    // 尝试开启对端的mq
    int fail_count = 0;
    sprintf(recv_buf, "/%s", argv[2]);
    while (fail_count < 10)
    {
        peer_mq = mq_open(recv_buf, O_RDWR);
        if (peer_mq > 0)
        {
            // 开启成功
            break;
        }
        fail_count++;
        printf("对端%s还未准备就绪\n", argv[2]);
        sleep(1);
    }

    if (fail_count == 10)
    {
        printf("对端不存在！\n");
        exit(EXIT_FAILURE);
    }

    // 对端开启成功，启动子线程接收对端的数据
    pthread_create(&recv_thread, NULL, recv_thread_func, (void *)argv[2]);

    // 读取标准输入，发送到消息队列
    while (1)
    {
        scanf("%s", send_buf);
        mq_send(my_mq, send_buf, BUF_LEN, 0);
    }

    return 0;
}
